<?php

require_once('interfaces/RequestMapping.interface.php');
require_once('classes/Mapping/AbstractMappingConfig.class.php');
require_once('classes/SimpleModel.class.php');

class VariableMappingConfig extends AbstractMappingConfig implements RequestMapping{

    protected $from;
    protected $to;
    protected $parent;
    protected $model;

    public function VariableMappingConfig($fromUri, $toFile){
        $to = $_SERVER['DOCUMENT_ROOT'].$toFile;
        if (file_exists($to)){
            $this->from = $fromUri;
            $this->to = $to;
            $this->model = new SimpleModel();
            return true;
        }else{
            throw new Exception('Couldn\'t find the file');
        }
    }

    public function checkMapping($uri){
        if (!$this->configObj->conditionsMet()){
            return false;
        }
        $actualUriParts = explode('/',$uri);
        $intendedUriParts = explode('/',$this->from);
        if (count($actualUriParts) != count($intendedUriParts)){
            //print 'false 0<br/>';
            return false;
        }
        foreach ($actualUriParts as $key => $actualUriPart){
            $intendedUriPart = $intendedUriParts[$key];
            $variableBgnPos = strpos($intendedUriPart,'{');
            $variableEndPos = strpos($intendedUriPart,'}',$variableBgnPos);
            if ($intendedUriPart == $actualUriPart && ($variableBgnPos === false || $variableEndPos === false)){ // if they're exactly the same with no intended variables
                //print "continuing, $intendedUriPart == $actualUriPart<br/>";
                continue; // Carry on to the next part
            }
            // at this stage there must be a well-formed variable
            if ($variableBgnPos > 0 && substr($actualUriPart,0,$variableBgnPos) != substr($intendedUriPart,0,$variableBgnPos)){
                //print 'false 1 - '.$variableBgnPos.' > 0 && '.substr($actualUriPart,0,$variableBgnPos).' != '.substr($intendedUriPart,0,$variableBgnPos).'<br/>';
                return false; // If the start of the variable isn't at the start of the uri part and everything before doesn't match the whole URI can't be interpreted
            }
            $variableEndFromStringEnd = strlen($intendedUriPart) - $variableEndPos-1; // work out how far from the end the variable is
            if ($variableEndFromStringEnd > 0 && substr($actualUriPart,-$variableEndFromStringEnd) != substr($intendedUriPart,-$variableEndFromStringEnd)){
                //print 'false 2 - '.$variableEndFromStringEnd.' > 0 && '.substr($actualUriPart,-$variableEndFromStringEnd).' != '.substr($intendedUriPart,-$variableEndFromStringEnd).'<br/>';
                return false; // If the start of the variable ends before the end of the uri part and everything afterward doesn't match the whole URI can't be interpreted
            }
            $key = substr($intendedUriPart,$variableBgnPos+1,strlen($intendedUriPart)-($variableEndFromStringEnd+$variableBgnPos)-2);
            $val = urldecode(substr($actualUriPart  ,$variableBgnPos,strlen($actualUriPart)  -($variableEndFromStringEnd+$variableBgnPos)));
            //$val = substr($actualUriPart  ,$variableBgnPos+1,$variableEndPos-1);
            $this->model->put($key,$val);
        }
        return true;
    }

    protected function includeFile($fileLocation){
        $model = $this->model;
        if (file_exists($fileLocation)){
            include($fileLocation);
            return true;
        }else{
            throw new Exception('Couldn\'t find the file');
        }
    }

    public function run(){
        $this->configObj->run();
        $this->includeFile($this->to);
    }

    public static function interpretXmlConfig(/*XMLNodeList?*/ $item, /*RequestInterpreter*/ $interpreter){
        $tmp_doc = new DOMDocument();
        $tmp_doc->appendChild($tmp_doc->importNode($item,true));

        $from = $tmp_doc->getElementsByTagName('from')->item(0);
        $to = $tmp_doc->getElementsByTagName('to')->item(0);
        $name = $item->localName;
        $interpreter->addMapping(new $name($from->textContent,$to->textContent));
    }

}

?>